package com.yuanss.backenddemo.auth.realm;

import com.yuanss.backenddemo.dao.SysUserDao;
import com.yuanss.backenddemo.dao.SysUserRoleDao;
import com.yuanss.backenddemo.entity.po.SysUser;
import com.yuanss.backenddemo.utils.JWTUtils;
import com.yuanss.backenddemo.auth.token.JwtToken;
import com.yuanss.backenddemo.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author yuanss
 * @version 1.0
 * @description
 * @date 2024/6/12 20:25:34
 */
@Slf4j
@Component
public class MyRealm extends AuthorizingRealm {

    @Resource
    private SysUserRoleDao sysUserRoleDao;

    @Resource
    private SysUserDao sysUserDao;


    /**
     * 判断当前传入的token是否是JwtToken
     * */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 授权
     * 只有当检测用户需要权限或者需要判定角色的时候才会走
     * */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取登录用户信息
        Long userId = ShiroUtils.getUserId();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        List<String> roleCodes = sysUserRoleDao.queryRoleCodeByUserId(userId);
        if(!roleCodes.isEmpty()){
            roleCodes.forEach(info::addRole);
        }
        // 返回授权信息
        return info;
    }

    /**
     * 验证token
     * */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取token
        String jwt = (String) authenticationToken.getCredentials();
        // 验证token
        if (!JWTUtils.verify(jwt)) {
            throw new AuthenticationException("Token认证失败");
        }
        // 查询数据库
        String username = JWTUtils.getClaim(jwt, "username");
        SysUser sysUser = sysUserDao.selectByUserName(username);
        if(ObjectUtils.isEmpty(sysUser)){
            throw new AuthenticationException("用户不存在");
        }
        // 返回认证信息
        return new SimpleAuthenticationInfo(sysUser, jwt, "MyRealm");
    }

}
